package com.wpml.netty.rpc;

import com.wpml.netty.rpc.client.ClientFactory;
import com.wpml.netty.rpc.common.MyBody;
import com.wpml.netty.rpc.common.MyHeader;
import com.wpml.netty.rpc.service.Car;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;

/**
 * @Description
 * @Date 2021-05-06
 * @Author wangpei
 **/
@SuppressWarnings("all")
public class ProxyFactory {

    public static void main(String[] args) {
        ClassLoader classLoader = Car.class.getClassLoader();
        System.out.println(Car.class.getName());
        System.out.println(classLoader.getClass().getName());
    }

    public static <T> T getProxy(Class<T> interfaceInfo) {

        ClassLoader classLoader = interfaceInfo.getClassLoader();

        Class<?>[] method = {interfaceInfo};

        Dispatcher dis = Dispatcher.getInstance();

        return (T) Proxy.newProxyInstance(classLoader, method, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                String name = interfaceInfo.getName();
                String methodName = method.getName();
                Class<?>[] parameterTypes = method.getParameterTypes();
                // 判断是否本地调用
                Object obj = dis.get(name);
                if (obj != null) {
                    System.out.println("======本地调用=======");
                    Class<?> clazz = obj.getClass();
                    Object res = null;
                    try {
                        Method invokeMethod = clazz.getMethod(methodName, parameterTypes);
                        res = invokeMethod.invoke(obj, args);

                    } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                    return res;
                }

                // RPC 调用
                // 消息体
                MyBody content = MyBody.builder()
                        .args(args)
                        .methodName(methodName)
                        .name(name)
                        .parameterTypes(parameterTypes)
                        .build();
                /*byte[] msgBody = SerDerUtil.ser(content);
                // 封装头信息
                MyHeader header = createHeader(msgBody);
                byte[] msgHeader = SerDerUtil.ser(header);
                // 获取连接
                ClientFactory factory = ClientFactory.getFactory();
                NioSocketChannel clientChannel = factory.getClient(new InetSocketAddress("localhost", 9090));
                ByteBuf byteBuf = PooledByteBufAllocator.DEFAULT.directBuffer(msgHeader.length + msgBody.length);
                CompletableFuture<Object> response = new CompletableFuture<>();
                // 注册回调
                ResponseCallback.addCallback(header.getRequestID(), response);
                byteBuf.writeBytes(msgHeader);
                byteBuf.writeBytes(msgBody);
                ChannelFuture channelFuture = clientChannel.writeAndFlush(byteBuf);
                channelFuture.sync();*/

                CompletableFuture<Object> response = ClientFactory.transport(content);

                return response.get();
            }
        });
    }


    public static MyHeader createHeader(byte[] msg) {
        int size = msg.length;
        int f = 0x14141414;
        long requestID = Math.abs(UUID.randomUUID().getLeastSignificantBits());
        //0x14  0001 0100

        return MyHeader.builder()
                .flag(f)
                .dataLen(size)
                .requestID(requestID)
                .build();
    }
}
